package com.hqd.ch03.v19.aop.support;

import com.hqd.ch03.v19.aop.DynamicIntroductionAdvice;
import com.hqd.ch03.v19.aop.IntroductionInterceptor;
import com.hqd.ch03.v19.aop.ProxyMethodInvocation;
import com.hqd.ch03.v19.aopalliance.intercept.MethodInvocation;
import org.junit.Assert;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.lang.reflect.Method;

public class DelegatingIntroductionInterceptor extends IntroductionInfoSupport implements IntroductionInterceptor {
    private Object delegate;

    public DelegatingIntroductionInterceptor(Object delegate) {
        init(delegate);
    }

    private void init(Object delegate) {
        Assert.assertNotNull("Delegate must not be null", delegate);
        this.delegate = delegate;
        implementInterfacesOnObject(delegate);

        /**
         * 删除没必要的接口
         */
        suppressInterface(IntroductionInterceptor.class);
        suppressInterface(DynamicIntroductionAdvice.class);
    }

    @Nullable
    @Override
    public Object invoke(@Nonnull MethodInvocation mi) throws Throwable {
        /**
         * 判断是否是对于接口方法
         * 是：则执行对应的接口方法
         * 否：则正常调用
         */
        if (isMethodOnIntroducedInterface(mi)) {
            Method method = mi.getMethod();
            Object retVal = method.invoke(this.delegate, mi.getArguments());
            /**
             * 如果返回当前对象，应该返回的是代理对象
             * 而不是引介对象
             */
            if (retVal == this.delegate && mi instanceof ProxyMethodInvocation) {
                Object proxy = ((ProxyMethodInvocation) mi).getProxy();
                if (mi.getMethod().getReturnType().isInstance(proxy)) {
                    retVal = proxy;
                }
            }
            return retVal;
        }
        return mi.proceed();
    }
}
